exports.iniExt = function(main){
	main.addExt({
		ini: function(){
			this.commands = {}; //[idcommand]
			this.commandPending = {}; //[iduser][idcommand]
		}
		
		/*
		Add new command to the command list.
		commandDef have the form: {
			r : COMMANDID, //request
			fun: COMMANDFUN(command) //if the command is an output command :: needs confirmation, but not data.
			,answerFun: COMMANDANSWERFUN(command) //if the command is an input command.
		}
		*/
		,addNewCommand: function(commandDef){
			if( !this.checkCommand(commandDef.r) ){
				this.commands[commandDef.r] = {
					fun : (commandDef.fun) ? commandDef.fun : this.makeAnswer
					,answerFun: commandDef.answerFun
				};
			} else {
				console.log("Error adding new command. Command duplicated.");
			}
		}
	
		//Check if a command is into command list.
		,checkCommand: function(request){
			if( request && this.commands[request] ) return true;
			else return false;
		}
	
		/*All command object have the form:
			c : {
				r : COMMANDID, //request
				idc: IDCOMMAND
				, (....)
			}
		*/
		,executeCommandForClient: function(client, command){
			if( this.checkCommand(command.r) ){
				var f = this.commands[command.r].fun.bind(this);
				var answer = f(client, command);
			} else
				var answer = this.makeAnswer(command);
			return answer;
		}
		,processAnswerForClient: function(client, answer){
			var cp = this.clients[client.id].commandPending[answer.idc];
			if( cp ) {
				this.commands[cp.r].answerFun.bind(this, client, answer.answer)();
				delete this.clients[client.id].commandPending[answer.idc];
			} else
				console.log("Respuesta desconocida.");
		}
		,makeAndSendCommand: function(request, args){
			var l = Object.getLength(this.clients[client.id].commandPending);
			var command = {r: request, idc: l, 'args': args};
			this.clients[client.id].commandPending[l] = command; //Save the command in pending commands for an answer.
		
			this.sendCommand(command);
		}
		,makeCommand: function(client, request, args){
			console.log("Comando haciendose para: "+client.id);
			if( !this.clients[client.id].commandPending )
				this.clients[client.id].commandPending = {};
			var cp = this.clients[client.id].commandPending;
			var l = Object.getLength(cp);
			var command = {r: request, idc: l, 'args': args};
			cp[l] = command; //Save the command in pending commands for an answer.
			return command;
		}
		
		//return a valid answer object. If answer is false or null it is considered a failed answer.
		,makeAnswer: function(command, answer){
			if(!answer) return {idc: command.idc , 'answer' : 'fail'};
			else return {idc: command.idc , 'answer' : answer};
		}
		
		//commandAll es un array con cada "comando" que se enviará.
		,makeAnswerForAll: function(command, answer, commandAll, br){
			return {self: {idc: command.idc, 'answer': answer}, command: commandAll, 'br': br};
		}
		,sendAnswer: function(client, answer){
			this.clients[client.id].socket.emit('answer', answer);
		}
		,sendAnswerForAll: function(client, answer){
			var c = this.clients[client.id];
			var ch = this.chats[ c.idchat ];
			
			if(answer.command.length > 0) {
				Object.each(ch.clients, function(sa){
					if(sa.id == c.id) return;
					this.clients[sa.id].socket.emit('command', answer.command.shift());
				} ,this);
			}
			c.socket.emit('answer', answer.self);
		}
		,sendCommand: function(client, command){
			this.clients[client.id].socket.emit('command', command);
		}
	});
}
